#ifndef DW_GRAPHICS_PARTICLEEMITTER_H
# define DW_GRAPHICS_PARTICLEEMITTER_H

#	include "graphics/object.h"

namespace dw
{
	namespace graphics
	{

		using maths::Vector2f;
		using maths::Point3f;
		using maths::Vector3f;

		class Renderer;

		class Particle
		{
		public :
			
			Particle();

		public :
			
			bool update(const float dT);

		public :

			Point3f position;
			
			Vector3f velocity;
			
			float ttl;
			
			float mass;
			
			Vector3f forceSum;

		};

		class IParticleEmitter : public Object
		{
		public :

			IParticleEmitter(const Point3f& position, const uint32 particleCount, const std::string& name);
			
			~IParticleEmitter();

		public :
			
			const std::string& getName() const { return _name; }

			void setParticleCount(const uint32 particleCount);
			
			uint32 getParticleCount() const { return _particleCount; }

			void setPosition(const Point3f & position) { _position = position; }
			
			const Point3f& getPosition() const { return _position; }

		public :

			virtual void update(const float dT) = 0;
			
			virtual void reset(Particle & particle) = 0;
			
			virtual void render() const = 0;

		protected :
			
			const std::string 		_name;
			
			std::vector< Particle >	_particles;
			
			uint32 _particleCount;
			
			Point3f _position;

		};

		class Spray : public IParticleEmitter
		{
		public :

			Spray(const std::string & name);
			
			Spray(const Point3f & position, const Vector3f & direction, const uint32 particleCount, const std::string & name);

		public :
			
			void update(const float dT);
			
			void render(Renderer * renderer) const ;

		public :	
			
			void setVelocity(float averageVelocity, float delta);
			
			void setTTL(float averageTTL, float delta);
			
			void setMass(float averageMass, float delta);
			
			void setDeltaAngle(const Vector2f deltaAngle);
			
			void setDeltaPosition(const Vector3f deltaPosition);

		private :
			
			void reset(Particle & particle);

		public :
			
			Vector3f getNormal(const Point3f& p)	const { return _direction; }
			
			bool intersects(const Ray& ray)	const { return false; }

		private :
			
			Vector3f _direction;
			
			float _rof;

			float _last;

			float _aVelocity;
			float _dVelocity;

			float _aTTL;
			float _dTTL;

			float _aMass;
			float _dMass;

			Vector2f _dAngle;
			Vector3f _dPosition;
		};

	} // namespace graphics
} // namespace dw

#endif	// DW_GRAPHICS_PARTICLEEMITTER_H